package forJava;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectTest {

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {
        // 知道具体类
        Class<Dog> dogClz1 = Dog.class;
        System.out.println(dogClz1.getName());

        // 通过 Class.forName()传入类的路径获取
        Class<?> dogClz2 = Class.forName("forJava.Dog");
        System.out.println(dogClz2.getName());

        // 通过类加载器xxxClassLoader.loadClass()传入类路径获取:
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        Class<?> dogClz3 = classLoader.loadClass("forJava.Dog");
        System.out.println(dogClz3.getName());

        // 通过实例获取
        Dog dog = new Dog();
        Class<? extends Dog> dogClz4 = dog.getClass();
        System.out.println(dogClz4.getName());

        // 开始反射Dog类,先获取实例
        Dog dog1 = dogClz1.newInstance();

        // 获取类中所有的方法(包括私有的)
        Method[] methods = dogClz1.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }

        // 调用方法
        Method saySomething = dogClz1.getDeclaredMethod("saySomething", String.class);
        saySomething.setAccessible(true);
        saySomething.invoke(dog1, "我被反射了~~~");

        // 获取所有字段
        Field[] fields = dogClz1.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }

        // 给name字段赋值
        Field name = dogClz1.getDeclaredField("name");
        name.setAccessible(true);
        name.set(dog1, "我也被反射了~~~");
        System.out.println(dog1.getName());
    }

}

class Dog {

    private String name;
    int age;

    private void saySomething(String words) {

        System.out.println(words);
    }

    public void sayGood() {

        System.out.println("good");
    }

    public String getName() {

        return name;
    }

}
